﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace TDBaseDataLibrary
{
    public class Particle_Node
    {
        public float stime;        //开始时间
        public float etime;        //结束时间
        public float ctime;        //当前时间
        public Color color;        //颜色
        public float speed;        //速度
        public float scale;        //放缩
        public float rotate;       //旋转
        public float direct;
        public Vector2 sPos;
        public Vector2 ePos;
        public Vector2 cPos;
    }
    public class Particle_Sender_Info
    {
        public float centerX;
        public float centerY;
        public float angleRange;        //角度范围
        public float countPerFrame;    //数目
        public float direct;
        public float minLift;
        public float maxLift;
        public float minSpeed;
        public float maxSpeed;
        public float minScale;
        public float maxScale;
        public string szTexName;
        public List<Color> colorList;
    }
    public class Particle_Sender
    {
        public Vector2 pos;
        public Particle_Sender_Info SenderInfo;
        public List<Particle_Node> nodeList;

        public Texture2D Particle_tex;
        float fstime;           //开始时间
        float ftemptime;
        bool start;
        public float Direct
        {
            set { SenderInfo.direct = value; }
            get { return SenderInfo.direct; }
        }
        
        public Particle_Sender()
        {
        }
        public Particle_Sender(ContentManager Content,Particle_Sender_Info Info,Vector2 vPos)
        {
            Particle_Sender_Create(Content,Info, vPos);
        }
        public Particle_Sender(Texture2D tex2D,Vector2 vCenter,Vector2 vPos,float angleRange,float count)
        {
            start = false;
            Particle_tex = tex2D;
            SenderInfo = new Particle_Sender_Info();
            if(vCenter==null)
            {
                SenderInfo.centerX = tex2D.Width / 2;
                SenderInfo.centerY = tex2D.Height / 2;
            }
            else
            {
                SenderInfo.centerX = vCenter.X;
                SenderInfo.centerY = vCenter.Y;
            }
            
            SenderInfo.angleRange = angleRange;
            SenderInfo.countPerFrame = 2;
            SenderInfo.minLift = 200;
            SenderInfo.maxLift = 1000;
            SenderInfo.minSpeed = 5;
            SenderInfo.maxSpeed = 5;
            SenderInfo.minScale = 0.0f;
            SenderInfo.maxScale = 1.0f;
            SenderInfo.colorList = new List<Color>();
            Color c = new Color(255, 114, 0, 255);
            SenderInfo.colorList.Add(c);
            c = new Color(255, 157, 0, 255);
            SenderInfo.colorList.Add(c);
            c = new Color(255, 0, 40, 255);
            SenderInfo.colorList.Add(c);
            c = new Color(0, 0, 0, 0);
            SenderInfo.colorList.Add(c);
            nodeList = new List<Particle_Node>();
            pos = vPos;
        }
        public void Particle_Sender_Create(ContentManager Content,Particle_Sender_Info Info,Vector2 vPos)
        {
            SenderInfo = Info;
            Content.Load<Texture2D>(SenderInfo.szTexName);
            pos = vPos;
            nodeList = new List<Particle_Node>();
        }
        public void Start(GameTime time)
        {
            start = true;
            fstime = (float)time.TotalGameTime.TotalMilliseconds;
            ftemptime = 40;
 //           GenParticle(time);
        }
        public void Stop(GameTime stop)
        {
            start = false;
            ftemptime = 0;
        }
        void GenParticle(GameTime time)
        {
            Random r = new Random();
            for (int i = 0; i < SenderInfo.countPerFrame; i++)
            {
                Particle_Node node = new Particle_Node();
                node.stime = (float)time.TotalGameTime.TotalMilliseconds;
                node.etime = node.stime + r.Next((int)SenderInfo.minLift, (int)SenderInfo.maxLift);
                node.ctime = node.stime;
                node.color = SenderInfo.colorList[0];
                node.speed = r.Next((int)SenderInfo.minSpeed, (int)SenderInfo.maxSpeed);
                node.scale = SenderInfo.minScale;
                node.direct = SenderInfo.direct + r.Next((int)(-SenderInfo.angleRange * 100 / 2), (int)(SenderInfo.angleRange * 100 / 2)) / 100.0f;
                node.rotate = 0;
                node.sPos = pos;
                node.ePos.X = (float)(pos.X  -Math.Sin(node.direct) * (node.etime - node.stime) * node.speed / 1000);
                node.ePos.Y = (float)(pos.Y + Math.Cos(node.direct) * (node.etime - node.stime) * node.speed / 1000);
                node.cPos = node.sPos;
                nodeList.Add(node);
            }
        }
        public void Update(GameTime time)
        {
            if (start)
            {
                ftemptime += (float)time.TotalGameTime.TotalMilliseconds;
                if (ftemptime >= 40)
                {
                    ftemptime -= 40;
                    GenParticle(time);
                }
            }
            for (int i = nodeList.Count - 1; i >= 0; i--)
            {
                Particle_Node node = nodeList[i];
                node.ctime = (float)time.TotalGameTime.TotalMilliseconds;
                if (node.ctime - node.stime <= 0)
                    continue;
                float rate = (node.ctime - node.stime) / (node.etime - node.stime);
                if (rate >= 1)
                {
                    nodeList.RemoveAt(i);
                    continue;
                }
                node.scale = rate * (SenderInfo.maxScale - SenderInfo.minScale) + SenderInfo.minScale;
                if(rate < 0.5f)
                    node.color = Color.Lerp(SenderInfo.colorList[0], SenderInfo.colorList[1], rate * 2);
                else if(rate >= 0.5f&& rate < 0.75f)
                    node.color = Color.Lerp(SenderInfo.colorList[1], SenderInfo.colorList[2], (rate - 0.5f) * 4);

                else
                    node.color = Color.Lerp(SenderInfo.colorList[2], SenderInfo.colorList[3], (rate - 0.75f) * 4);
                node.cPos.X = (node.ePos.X - node.sPos.X) * rate + node.sPos.X;
                node.cPos.Y = (node.ePos.Y - node.sPos.Y) * rate + node.sPos.Y;
            }
        }
        public void Draw(GraphicsDeviceManager graphics, GameTime gameTime, SpriteBatch spriteBatch,float offsetX,float offsetY,bool add)
        {
            Rectangle rtSrc = new Rectangle(0,0,Particle_tex.Width,Particle_tex.Height);
            if (add == true)
            {
                spriteBatch.End();
                spriteBatch.Begin(SpriteSortMode.BackToFront,BlendState.Additive);
            }
            for (int i = nodeList.Count - 1; i >= 0 ; i--)
            {
                Vector2 vPos = nodeList[i].cPos;
                vPos.X += offsetX;
                vPos.Y += offsetY;
                Vector2 vCenter = new Vector2(SenderInfo.centerX,SenderInfo.centerY);
                spriteBatch.Draw(Particle_tex,
                    vPos,
                    rtSrc, nodeList[i].color, nodeList[i].direct, vCenter, nodeList[i].scale, SpriteEffects.None, 0.0f);
            }
            if (add == true)
            {
                spriteBatch.End();
                spriteBatch.Begin(SpriteSortMode.BackToFront,BlendState.AlphaBlend);
            }
        }
    }

    public class Particle
    {
        //粒子图像
        protected  Vector2 Pos;
        protected  List<Particle_Sender> senderList;
        public float Direct
        {
            set { senderList[0].Direct = value; }
            get { return senderList[0].Direct; }
        }
        public void Start(GameTime time)
        {
            for (int i = 0; i < senderList.Count; i++)
                senderList[i].Start(time);
        }
        public void Stop(GameTime time)
        {
            for (int i = 0; i < senderList.Count; i++)
                senderList[i].Stop(time);
        }
        public Particle()
        {
        }

        public void AddSender(ContentManager Content,Particle_Sender_Info Info,Vector2 vPos)
        {
            Particle_Sender pSender = new Particle_Sender(Content,Info, vPos);
            senderList.Add(pSender);
        }

        public Particle(ContentManager content,Vector2 pos)
        {
            //senderList = new List<Particle_Sender>();
            //Pos = pos;
            //Particle_Sender Sender = new Particle_Sender(tex, vCenter, pos, 3.1415926f * 15 /180, 30);
            //senderList.Add(Sender);
        }
        public void Update(GameTime time)
        {
            for(int i = 0;i < senderList.Count;i ++)
                senderList[i].Update(time);
        }
        public virtual void Draw(GraphicsDeviceManager graphics, GameTime gameTime, SpriteBatch spriteBatch,float offsetX,float offsetY)
        {
            for (int i = 0; i < senderList.Count; i++)
                senderList[i].Draw(graphics, gameTime, spriteBatch,offsetX,offsetY,true);
        }
    }
    public class FireParticle : Particle
    {
        public FireParticle(ContentManager content,Vector2 pos)
            : base(content,pos)
        {
            senderList = new List<Particle_Sender>();
            Pos = pos;
            Vector2 v = new Vector2(64, 16);
            Particle_Sender Sender = new Particle_Sender(content.Load<Texture2D>("plumeD1"), v, pos, 3.1415926f * 15 / 180, 30);

            Sender.SenderInfo.centerX = 64;
            Sender.SenderInfo.centerY = 16;
            Sender.SenderInfo.countPerFrame = 2;
            Sender.SenderInfo.minLift = 200;
            Sender.SenderInfo.maxLift = 1000;
            Sender.SenderInfo.minSpeed = 5;
            Sender.SenderInfo.maxSpeed = 200;
            Sender.SenderInfo.minScale = 0.0f;
            Sender.SenderInfo.maxScale = 1.0f;
            Sender.SenderInfo.colorList = new List<Color>();
            Color c = new Color(255, 114, 0, 255);
            Sender.SenderInfo.colorList.Add(c);
            c = new Color(255, 157, 0, 255);
            Sender.SenderInfo.colorList.Add(c);
            c = new Color(255, 0, 40, 255);
            Sender.SenderInfo.colorList.Add(c);
            c = new Color(0, 0, 0, 0);
            Sender.SenderInfo.colorList.Add(c);

            senderList.Add(Sender);
        }
    }

    public class WaterParticle : Particle
    {
        public WaterParticle(ContentManager content, Vector2 pos)
            : base(content, pos)
        {
            senderList = new List<Particle_Sender>();
            Texture2D tex = content.Load<Texture2D>("Water");
            Vector2 v = new Vector2(64, 0);

            Particle_Sender Sender = new Particle_Sender(tex, v, pos, 3.1415926f * 15 / 180, 30);

            Sender.SenderInfo.countPerFrame = 1;
            Sender.SenderInfo.centerX = 64;
            Sender.SenderInfo.centerY = 0;
            Sender.SenderInfo.minLift = 200;
            Sender.SenderInfo.maxLift = 1000;
            Sender.SenderInfo.minSpeed = 5;
            Sender.SenderInfo.maxSpeed = 200;
            Sender.SenderInfo.minScale = 0.0f;
            Sender.SenderInfo.maxScale = 1.0f;
            Sender.SenderInfo.colorList = new List<Color>();
            Color c = new Color(235,254, 255, 255);
            Sender.SenderInfo.colorList.Add(c);
            c = new Color(235, 254, 255, 255);
            Sender.SenderInfo.colorList.Add(c);
            c = new Color(189, 207, 208, 255);
            Sender.SenderInfo.colorList.Add(c);
            c = new Color(0, 0, 0, 0);
            Sender.SenderInfo.colorList.Add(c);
            senderList.Add(Sender);
        }
        public override void Draw(GraphicsDeviceManager graphics, GameTime gameTime, SpriteBatch spriteBatch, float offsetX, float offsetY)
        {
            for (int i = 0; i < senderList.Count; i++)
                senderList[i].Draw(graphics, gameTime, spriteBatch, offsetX, offsetY, false);
        }
    }
    public class SplashParticle : Particle
    {
        public SplashParticle(ContentManager content, Vector2 pos)
            : base(content, pos)
        {
            senderList = new List<Particle_Sender>();
            Texture2D tex = content.Load<Texture2D>("fireArrow");
            Vector2 v = new Vector2(tex.Width / 2, tex.Height/2);
            Particle_Sender Sender = new Particle_Sender(tex, v, pos, 6.28f, 30);
            
            Sender.SenderInfo.countPerFrame = 1;
            Sender.SenderInfo.minLift = 20;
            Sender.SenderInfo.maxLift = 100;
            Sender.SenderInfo.minSpeed = 0;
            Sender.SenderInfo.maxSpeed = 0;
            Sender.SenderInfo.minScale = 0.0f;
            Sender.SenderInfo.maxScale = 0.8f;
            Sender.SenderInfo.colorList = new List<Color>();
            Color c = new Color(235, 254, 255, 255);
            Sender.SenderInfo.colorList.Add(c);
            c = new Color(235, 254, 255, 255);
            Sender.SenderInfo.colorList.Add(c);
            c = new Color(189, 207, 208, 255);
            Sender.SenderInfo.colorList.Add(c);
            c = new Color(0, 0, 0, 0);
            Sender.SenderInfo.colorList.Add(c);
            senderList.Add(Sender);
        }
        public override void Draw(GraphicsDeviceManager graphics, GameTime gameTime, SpriteBatch spriteBatch, float offsetX, float offsetY)
        {
            for (int i = 0; i < senderList.Count; i++)
                senderList[i].Draw(graphics, gameTime, spriteBatch, offsetX, offsetY, false);
        }
    }
}
